﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace WindowsGame1
{
    class Monster
    {
        Model monster;
        Vector3 location;
        bool leftThighFront;
        float bodyRotation;

        ModelBone pelvis; // everything connected to pelvis (whole body)
        ModelBone spinePart0; ModelBone spinePart1; ModelBone spinePart2; ModelBone spinePart3;

        // BONES
        // Head
        ModelBone neck;
        ModelBone head;
        ModelBone mouth;
        ModelBone rightAntenna;
        ModelBone leftAntenna;
        ModelBone rightMouthHorn;
        ModelBone leftMouthHorn;

        // Arms
        ModelBone leftClavicle;
        ModelBone leftUpperArm;
        ModelBone leftForearm;
        ModelBone leftHand;
        ModelBone leftFinger0; ModelBone leftFinger1; ModelBone leftFinger2; ModelBone leftFinger3; ModelBone leftFinger4;
        ModelBone rightClavicle;
        ModelBone rightUpperArm;
        ModelBone rightForearm;
        ModelBone rightHand;
        ModelBone rightFinger0; ModelBone rightFinger1; ModelBone rightFinger2; ModelBone rightFinger3; ModelBone rightFinger4;

        // Legs
        ModelBone leftThigh;
        ModelBone leftCalf;
        ModelBone leftFoot;
        ModelBone leftToe0; ModelBone leftToe1; ModelBone leftToe2; ModelBone leftToe3;
        ModelBone rightThigh;
        ModelBone rightCalf;
        ModelBone rightFoot;
        ModelBone rightToe0; ModelBone rightToe1; ModelBone rightToe2; ModelBone rightToe3;

        // Store the original transform matrix for each animating bone.
        Matrix pelvisTransform;
        Matrix spinePart0Transform; Matrix spinePart1Transform; Matrix spinePart2Transform; Matrix spinePart3Transform;
        Matrix neckTransform;
        Matrix headTransform;
        Matrix mouthTransform;
        Matrix rightAntennaTransform;
        Matrix leftAntennaTransform;
        Matrix rightMouthHornTransform;
        Matrix leftMouthHornTransform;
        Matrix leftClavicleTransform;
        Matrix leftUpperArmTransform;
        Matrix leftForearmTransform;
        Matrix leftHandTransform;
        Matrix leftFinger0Transform; Matrix leftFinger1Transform; Matrix leftFinger2Transform; Matrix leftFinger3Transform; Matrix leftFinger4Transform;
        Matrix rightClavicleTransform;
        Matrix rightUpperArmTransform;
        Matrix rightForearmTransform;
        Matrix rightHandTransform;
        Matrix rightFinger0Transform; Matrix rightFinger1Transform; Matrix rightFinger2Transform; Matrix rightFinger3Transform; Matrix rightFinger4Transform;
        Matrix leftThighTransform;
        Matrix leftCalfTransform;
        Matrix leftFootTransform;
        Matrix leftToe0Transform; Matrix leftToe1Transform; Matrix leftToe2Transform; Matrix leftToe3Transform;
        Matrix rightThighTransform;
        Matrix rightCalfTransform;
        Matrix rightFootTransform;
        Matrix rightToe0Transform; Matrix rightToe1Transform; Matrix rightToe2Transform; Matrix rightToe3Transform;

        // Array holding all the bone transform matrices for the entire model.
        Matrix[] boneTransforms;

        // Current animation positions.
        float leftThighRotationValue;
        float leftCalfRotationValue;
        float leftFootRotationValue;
        float rightThighRotationValue;
        float rightCalfRotationValue;
        float rightFootRotationValue;

        public float LeftThighRotation
        {
            get { return leftThighRotationValue; }
            set { leftThighRotationValue = value; }
        }
        public float RightThighRotation
        {
            get { return rightThighRotationValue; }
            set { rightThighRotationValue = value; }
        }
        public float LeftCalfRotation
        {
            get { return leftCalfRotationValue; }
            set { leftCalfRotationValue = value; }
        }
        public float RightCalfRotation
        {
            get { return rightCalfRotationValue; }
            set { rightCalfRotationValue = value; }
        }
        public float LeftFootRotation
        {
            get { return leftFootRotationValue; }
            set { leftFootRotationValue = value; }
        }
        public float RightFootRotation
        {
            get { return rightFootRotationValue; }
            set { rightFootRotationValue = value; }
        }

        public Monster(Vector3 startingLocation)
        {
            location = startingLocation;
            leftThighFront = true;
            leftThighRotationValue = (float)Math.PI;
            rightThighRotationValue = -(float)Math.PI;
            bodyRotation = 90f;
        }

        /// <summary>
        /// Loads model.
        /// </summary>
        public void Load(ContentManager content)
        {
            monster = content.Load<Model>("Umber Hulk1");

            pelvis = monster.Bones["Bip001 Pelvis"];
            spinePart0 = monster.Bones["Bip001 Spine"];
            spinePart1 = monster.Bones["Bip001 Spine1"];
            spinePart2 = monster.Bones["Bip001 Spine2"];
            spinePart3 = monster.Bones["Bip001 Spine3"];

            neck = monster.Bones["Bip001 Neck"];
            head = monster.Bones["Bip001 Head"];
            mouth = monster.Bones["Bip001 Xtra01 Mouth"];
            rightAntenna = monster.Bones["Bip001 Xtra02"];
            leftAntenna = monster.Bones["Bip001 Xtra02Opp"];
            rightMouthHorn = monster.Bones["Bip001 Xtra03"];
            leftMouthHorn = monster.Bones["Bip001 Xtra03Opp"];

            leftClavicle = monster.Bones["Bip001 L Clavicle"];
            leftUpperArm = monster.Bones["Bip001 L UpperArm"];
            leftForearm = monster.Bones["Bip001 L Forearm"];
            leftHand = monster.Bones["Bip001 L Hand"];
            leftFinger0 = monster.Bones["Bip001 L Finger0"];
            leftFinger1 = monster.Bones["Bip001 L Finger1"];
            leftFinger2 = monster.Bones["Bip001 L Finger2"];
            leftFinger3 = monster.Bones["Bip001 L Finger3"];
            leftFinger4 = monster.Bones["Bip001 L Finger4"];
            rightClavicle = monster.Bones["Bip001 R Clavicle"];
            rightUpperArm = monster.Bones["Bip001 R UpperArm"];
            rightForearm = monster.Bones["Bip001 L Forearm"];
            rightHand = monster.Bones["Bip001 R Hand"];
            rightFinger0 = monster.Bones["Bip001 R Finger0"];
            rightFinger1 = monster.Bones["Bip001 R Finger1"];
            rightFinger2 = monster.Bones["Bip001 R Finger2"];
            rightFinger3 = monster.Bones["Bip001 R Finger3"];
            rightFinger4 = monster.Bones["Bip001 R Finger4"];

            leftThigh = monster.Bones["Bip001 L Thigh"];
            leftCalf = monster.Bones["Bip001 L Calf"];
            leftFoot = monster.Bones["Bip001 L Foot"];
            leftToe0 = monster.Bones["Bip001 L Toe0"];
            leftToe1 = monster.Bones["Bip001 L Toe1"];
            leftToe2 = monster.Bones["Bip001 L Toe2"];
            leftToe3 = monster.Bones["Bip001 L Toe3"];
            rightThigh = monster.Bones["Bip001 R Thigh"];
            rightCalf = monster.Bones["Bip001 R Calf"];
            rightFoot = monster.Bones["Bip001 R Foot"];
            rightToe0 = monster.Bones["Bip001 R Toe0"];
            rightToe1 = monster.Bones["Bip001 R Toe1"];
            rightToe2 = monster.Bones["Bip001 R Toe2"];
            rightToe3 = monster.Bones["Bip001 R Toe3"];

            // Store the original transform matrix for each animating bone.
            pelvisTransform = pelvis.Transform;
            spinePart0Transform = spinePart0.Transform;
            spinePart1Transform = spinePart1.Transform;
            spinePart2Transform = spinePart2.Transform;
            spinePart3Transform = spinePart3.Transform;
            neckTransform = neck.Transform;
            headTransform = head.Transform;
            mouthTransform = mouth.Transform;
            rightAntennaTransform = rightAntenna.Transform;
            leftAntennaTransform = leftAntenna.Transform;
            rightMouthHornTransform = rightMouthHorn.Transform;
            leftMouthHornTransform = leftMouthHorn.Transform;
            leftClavicleTransform = leftClavicle.Transform;
            leftUpperArmTransform = leftUpperArm.Transform;
            leftForearmTransform = leftForearm.Transform;
            leftHandTransform = leftHand.Transform;
            leftFinger0Transform = leftFinger0.Transform;
            leftFinger1Transform = leftFinger1.Transform;
            leftFinger2Transform = leftFinger2.Transform;
            leftFinger3Transform = leftFinger3.Transform;
            leftFinger4Transform = leftFinger4.Transform;
            rightClavicleTransform = rightClavicle.Transform;
            rightUpperArmTransform = rightUpperArm.Transform;
            rightForearmTransform = rightForearm.Transform;
            rightHandTransform = rightHand.Transform;
            rightFinger0Transform = rightFinger0.Transform;
            rightFinger1Transform = rightFinger1.Transform;
            rightFinger2Transform = rightFinger2.Transform;
            rightFinger3Transform = rightFinger3.Transform;
            rightFinger4Transform = rightFinger4.Transform;
            leftThighTransform = leftThigh.Transform;
            leftCalfTransform = leftCalf.Transform;
            leftFootTransform = leftFoot.Transform;
            leftToe0Transform = leftToe0.Transform;
            leftToe1Transform = leftToe1.Transform;
            leftToe2Transform = leftToe2.Transform;
            leftToe3Transform = leftToe3.Transform;
            rightThighTransform = rightThigh.Transform;
            rightCalfTransform = rightCalf.Transform;
            rightFootTransform = rightFoot.Transform;
            rightToe0Transform = rightToe0.Transform;
            rightToe1Transform = rightToe1.Transform;
            rightToe2Transform = rightToe2.Transform;
            rightToe3Transform = rightToe3.Transform;

            // Allocate the transform matrix array.
            boneTransforms = new Matrix[monster.Bones.Count];
        }

        public void Draw(Matrix world, Matrix view, Matrix projection)
        {
            // Set the world matrix as the root transform of the model.
            monster.Root.Transform = world;

            // Calculate matrices based on the current animation position.
            Matrix rightThighRotation = Matrix.CreateRotationX(rightThighRotationValue);
            Matrix rightCalfRotation = Matrix.CreateRotationX(rightCalfRotationValue);
            Matrix rightFootRotation = Matrix.CreateRotationX(rightFootRotationValue);
            Matrix leftThighRotation = Matrix.CreateRotationX(leftThighRotationValue);
            Matrix leftCalfRotation = Matrix.CreateRotationX(leftCalfRotationValue);
            Matrix leftFootRotation = Matrix.CreateRotationX(leftFootRotationValue);

            // Apply matrices to the relevant bones.
            rightThigh.Transform = rightThighRotation * rightThighTransform;
            leftThigh.Transform = leftThighRotation * leftThighTransform;

            // Look up combined bone matrices for the entire model.
            monster.CopyAbsoluteBoneTransformsTo(boneTransforms);

            // Draw the model.
            foreach (ModelMesh mesh in monster.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.World = boneTransforms[mesh.ParentBone.Index];
                    effect.View = view;
                    effect.Projection = projection;

                    effect.EnableDefaultLighting();
                }

                mesh.Draw();
            }
        }

        internal Vector3 GetLocation()
        {
            return location;
        }



        // Adjust a little of each the rotations
        internal void SwingThighs()
        {
            if (leftThighFront)
            {
                // swing leftThigh back
                leftThighRotationValue -= MathHelper.ToRadians(1);
                // swing rightThigh forward
                rightThighRotationValue += MathHelper.ToRadians(1);
                if (leftThighRotationValue <= MathHelper.ToRadians(-12)) // start moving it forward
                    leftThighFront = false;
            }
            else
            {
                // swing rightThigh back
                rightThighRotationValue -= MathHelper.ToRadians(1);
                // swing leftThigh forward
                leftThighRotationValue += MathHelper.ToRadians(1);
                if (leftThighRotationValue >= MathHelper.ToRadians(12)) // start moving it forward
                    leftThighFront = true;
            }
        }

        internal void MoveTowardsPlayer(Vector3 changeInLocation)
        {
            location += changeInLocation;
            if (changeInLocation.X != 0)
            {
                bodyRotation = Math.Sign(changeInLocation.X) * 90;
            }
            else
            {
                bodyRotation = 90 - Math.Sign(changeInLocation.Z) * 90;
            }
        }

        public float getBodyRotation()
        {
            return bodyRotation;
        }

        internal BoundingSphere GetBoundingSphere()
        {
            return new BoundingSphere(new Vector3(location.X, 10, location.Z), 33);
        }
    }
}